package com.rpc.dubbo.netty;


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.concurrent.DefaultThreadFactory;

import java.lang.reflect.Proxy;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author 何章怀晓 hezhanghuaixiao
 * @version V1.0
 * @desc
 */
public class NettyClient {
  //创建一个线程池
  ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 30, 2000, TimeUnit.SECONDS,
      new ArrayBlockingQueue<>(10), new DefaultThreadFactory("defaultFactory", false));
  private static NettyClientHandler client;

  //编写方法，使用代理模式，获取一个代理对象
  public Object getBean(final Class<?> serviceClass) {
    return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{serviceClass},
        (proxy, method, args) -> {
          System.out.println("代理被调用");
          if (client == null)
            initClient();
          //设置要发给服务器端的信息
          client.setPara(args[0].toString());
          return threadPoolExecutor.submit(client).get();
        });
  }


  //初始化客户端
  private static void initClient() {
    client = new NettyClientHandler();
    //创建EventLoopGroup
    NioEventLoopGroup group = new NioEventLoopGroup();
    try {
      Bootstrap bootstrap = new Bootstrap();
      bootstrap.group(group)
          .channel(NioSocketChannel.class)
          .option(ChannelOption.TCP_NODELAY, true)
          .handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
              ChannelPipeline pipeline = ch.pipeline();
              pipeline.addLast(new StringDecoder());
              pipeline.addLast(new StringEncoder());
              pipeline.addLast(client);
            }
          });
      ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 7000).sync();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

